#include "orangepch.h"
#include "OpenGlVertexArray.h"
#include "glad/glad.h"
namespace Orange {
	/// <summary>
	/// ���Զ���� shader type תΪ opengl �� ��׼ö������
	/// </summary>
	/// <param name="type"></param>
	/// <returns></returns>
	static GLenum ShaderTypeToOpenGLBaseEnum(ShaderDataType type) {
		switch (type)
		{
		case Orange::ShaderDataType::Float:  return GL_FLOAT;
		case Orange::ShaderDataType::Float2: return GL_FLOAT;
		case Orange::ShaderDataType::Float3: return GL_FLOAT;
		case Orange::ShaderDataType::Float4: return GL_FLOAT;
		case Orange::ShaderDataType::Mat3:	  return GL_FLOAT;
		case Orange::ShaderDataType::Mat4:	  return GL_FLOAT;
		case Orange::ShaderDataType::Int1:	  return GL_INT;
		case Orange::ShaderDataType::Int2:	  return GL_INT;
		case Orange::ShaderDataType::Int3:	  return GL_INT;
		case Orange::ShaderDataType::Int4:	  return GL_INT;
		case Orange::ShaderDataType::Bool:	  return GL_BOOL;
		}
		ORANGE_CORE_ASSERT(false, "ShaderDataType unknown!");
		return 0;
	}
	OpenGlVertexArray::OpenGlVertexArray()
	{
		glCreateVertexArrays(1, &m_RendererId);
	
	}

	OpenGlVertexArray::~OpenGlVertexArray()
	{
		glDeleteVertexArrays(1, &m_RendererId);
	}

	void OpenGlVertexArray::bind() const
	{
		glBindVertexArray(m_RendererId);
	}

	void OpenGlVertexArray::ubind() const
	{
		glBindVertexArray(0);
	}

	void OpenGlVertexArray::AddVertexBuffer(const Ref<VertexBuffer>& vertexBuffer)
	{
		/// <summary>
		/// ���°� ��������
		/// </summary>
		/// <param name="vertexBuffer"></param>
		glBindVertexArray(m_RendererId);

		vertexBuffer->bind();
		uint32_t index = 0;
		BufferLayout layout = vertexBuffer->getLayout();
		std::vector<BufferElement> elements = layout.GetElements();
		for (auto& element : elements) {
			glEnableVertexAttribArray(index);
			glVertexAttribPointer(
				index,
				element.GetComponentCount(element.m_type),
				ShaderTypeToOpenGLBaseEnum(element.m_type),
				element.m_normalized ? GL_TRUE : GL_FALSE,
				layout.GetStride(),
				(const void*)element.m_offset
			);
			index++;
		}

		m_vertexbuffers.push_back(vertexBuffer);
	}

	void OpenGlVertexArray::SetIndexBuffer(const Ref<IndexBuffer>& indexBuffer)
	{
		/// <summary>
		/// ���°� ��������
		/// </summary>
		/// <param name="vertexBuffer"></param>
		glBindVertexArray(m_RendererId);

		indexBuffer->bind();
		m_indexbuffer = indexBuffer;
	}
}
